package com.errol.batchprocessor.payroll;

import com.renjia.service.generic.log.LogService;
import com.renjia.service.generic.middleware.batchprocessor.abs.AbstractAdvisor;
import com.renjia.service.generic.middleware.batchprocessor.abs.AbstractAdvisorContainer;
import com.renjia.service.module.employeeaddition.advisorimpl.payroll.payload.PayrollEmployeeBatchPayload;
import com.renjia.service.module.employeeaddition.advisorimpl.payroll.payload.PayrollEmployeePiecePayload;
import com.renjia.service.module.employeeaddition.advisorimpl.payroll.payload.PayrollEmployeeSinglePayload;
import com.renjia.service.module.payroll.advisor.AbstractPayrollAdvisor;
import com.renjia.service.module.payroll.advisor.upload.PayrollUploadCheckAdvisor;
import com.renjia.service.module.payroll.advisor.upload.PayrollUploadCreateAdvisor;
import com.renjia.service.module.payroll.advisor.upload.PayrollUploadFailedAdvisor;
import com.renjia.service.module.payroll.advisor.upload.PayrollUploadPostAdvisor;
import com.renjia.service.module.payroll.advisor.verify.*;
import com.renjia.service.module.payroll.advisorimpl.payload.PayrollUploadBatchPayload;
import com.renjia.service.module.payroll.advisorimpl.payload.PayrollUploadSinglePayload;
import org.springframework.context.annotation.Primary;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;

/**
 * 费用发放上传和验证过程扩展点容器
 *
 * @author zhang xiao bin
 * @version v1.0
 * @date 2021/02/09
 * @since v5.0.6
 **/
@Primary
@Service
public class PayrollUploadVerifyAdvisorContainer
        extends AbstractAdvisorContainer<PayrollEmployeeBatchPayload>
        implements
        // 以下 1 行扩展点用于排款单上传阶段
        PayrollUploadCheckAdvisor, PayrollUploadCreateAdvisor, PayrollUploadPostAdvisor, PayrollUploadFailedAdvisor,
        // 以下 3 行扩展点用于排款单验证阶段
        PayrollVerifyBatchStartAdvisor,
        PayrollVerifySingleValidateAdvisor, PayrollVerifySingleValidateEmployeeAdvisor, PayrollVerifySingleProcessAdvisor,
        PayrollVerifySingleSuccessAdvisor, PayrollVerifySingleFailedAdvisor, PayrollVerifySinglePostAdvisor,
        PayrollVerifyPiecePostAdvisor {

    public PayrollUploadVerifyAdvisorContainer(LogService logService) {
        super(logService);
    }

    /**
     * 查找费用发放上传、验证的扩展点类型
     *
     * @param advisor 执行 setApplicationContext 方法的类实现的接口
     * @return AbstractPayrollAdvisor 的直接子类
     */
    @Override
    @SuppressWarnings("unchecked")
    protected Class<? extends AbstractAdvisor<PayrollEmployeeBatchPayload>> findAdvisorClass(Class<?> advisor) {
        Class<?> child = advisor;
        while (child.getInterfaces().length == 1) {
            if (AbstractPayrollAdvisor.class.equals(child.getInterfaces()[0])) {
                return (Class<? extends AbstractPayrollAdvisor>) child;
            } else {
                child = child.getInterfaces()[0];
            }
        }
        return null;
    }

    @Override
    public boolean doCheckBeforePayrollSavedAtUploadStage(@NonNull PayrollUploadBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollUploadCheckAdvisor.class, a -> a.doCheckBeforePayrollSavedAtUploadStage(batchPayload));
    }

    @Override
    public boolean doAfterNewPayrollRecordAtUploadStage(@NonNull PayrollUploadBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollUploadCreateAdvisor.class, a -> a.doAfterNewPayrollRecordAtUploadStage(batchPayload));
    }

    @Override
    public boolean doAfterNewPayrollDetailAtUploadStage(@NonNull PayrollUploadSinglePayload singlePayload, @NonNull PayrollUploadBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollUploadCreateAdvisor.class, a -> a.doAfterNewPayrollDetailAtUploadStage(singlePayload, batchPayload));
    }

    @Override
    public boolean doBeforeModifyPayrollDetailAtUploadStage(@NonNull PayrollUploadSinglePayload singlePayload, @NonNull PayrollUploadBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollUploadCreateAdvisor.class, a -> a.doBeforeModifyPayrollDetailAtUploadStage(singlePayload, batchPayload));
    }

    @Override
    public boolean doAfterPayrollSavedAtUploadStage(@NonNull PayrollUploadBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollUploadPostAdvisor.class, a -> a.doAfterPayrollSavedAtUploadStage(batchPayload));
    }

    @Override
    public boolean doBeforePayrollUploadReturnFail(@NonNull PayrollUploadBatchPayload batchPayload, @NonNull String errMsg) {
        boolean b = doCallBool(batchPayload, PayrollUploadFailedAdvisor.class, a -> a.doBeforePayrollUploadReturnFail(batchPayload, errMsg));
        removeAdvisorCacheForMission(batchPayload);
        return b;
    }

    @Override
    public boolean doPrepareOnBatchStartAtVerifyStage(@NonNull PayrollEmployeeBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollVerifyBatchStartAdvisor.class, a -> a.doPrepareOnBatchStartAtVerifyStage(batchPayload));
    }

    @Override
    public boolean doValidateBeforeFindEmployeeAtVerifyStage(@NonNull PayrollEmployeeSinglePayload singlePayload, @NonNull PayrollEmployeePiecePayload piecePayload, @NonNull PayrollEmployeeBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollVerifySingleValidateAdvisor.class, a -> a.doValidateBeforeFindEmployeeAtVerifyStage(singlePayload, piecePayload, batchPayload));
    }

    @Override
    public boolean doValidateAfterDealWithEmployeeAtVerifyStage(@NonNull PayrollEmployeeSinglePayload singlePayload, @NonNull PayrollEmployeePiecePayload piecePayload, @NonNull PayrollEmployeeBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollVerifySingleValidateEmployeeAdvisor.class, a -> a.doValidateAfterDealWithEmployeeAtVerifyStage(singlePayload, piecePayload, batchPayload));
    }

    @Override
    public boolean doExecuteOnEmployeeInfoSavedAtVerifyStage(@NonNull PayrollEmployeeSinglePayload singlePayload, @NonNull PayrollEmployeePiecePayload piecePayload, @NonNull PayrollEmployeeBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollVerifySingleProcessAdvisor.class, a -> a.doExecuteOnEmployeeInfoSavedAtVerifyStage(singlePayload, piecePayload, batchPayload));
    }

    @Override
    public boolean doSettleOnPayrollDetailValidateSuccessAtVerifyStage(@NonNull PayrollEmployeeSinglePayload singlePayload, @NonNull PayrollEmployeePiecePayload piecePayload, @NonNull PayrollEmployeeBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollVerifySingleSuccessAdvisor.class, a -> a.doSettleOnPayrollDetailValidateSuccessAtVerifyStage(singlePayload, piecePayload, batchPayload));
    }

    @Override
    public boolean doRecoverOnPayrollDetailValidateFailedAtVerifyStage(@NonNull PayrollEmployeeSinglePayload singlePayload, @NonNull PayrollEmployeePiecePayload piecePayload, @NonNull PayrollEmployeeBatchPayload batchPayload, @NonNull String errMsg) {
        return doCallBool(batchPayload, PayrollVerifySingleFailedAdvisor.class, a -> a.doRecoverOnPayrollDetailValidateFailedAtVerifyStage(singlePayload, piecePayload, batchPayload, errMsg));
    }

    @Override
    public boolean doCleanUpOnPayrollDetailProcessPostAtVerifyStage(@NonNull PayrollEmployeeSinglePayload singlePayload, @NonNull PayrollEmployeePiecePayload piecePayload, @NonNull PayrollEmployeeBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollVerifySinglePostAdvisor.class, a -> a.doCleanUpOnPayrollDetailProcessPostAtVerifyStage(singlePayload, piecePayload, batchPayload));
    }

    @Override
    public boolean doCleanUpOnPayrollDetailPieceProcessPostAtVerifyStage(@NonNull PayrollEmployeePiecePayload piecePayload, @NonNull PayrollEmployeeBatchPayload batchPayload) {
        return doCallBool(batchPayload, PayrollVerifyPiecePostAdvisor.class, a -> a.doCleanUpOnPayrollDetailPieceProcessPostAtVerifyStage(piecePayload, batchPayload));
    }
}
